/* sysLib.c - Xilinx Zynq-7000 board system-dependent library */

/*
 * Copyright (c) 2014-2018 Wind River Systems, Inc.
 *
 * The right to copy, distribute, modify or otherwise make use
 * of this software may be licensed only pursuant to the terms
 * of an applicable Wind River license agreement.
 */

/*
modification history
--------------------
19jan18,wch  updated to support endMacGet() (F6878)
15jan18,zpj  updated uVer of board descriptor to 2.0 (V7PRO-4241)
22may17,g_x  add zynq7kNetMalloc()/zynq7kNetFree() for un-cached IPNET tx
             buffer (V7PRO-3580)
15mar16,r_w  add INCLUDE_DEBUG_KPUTS for BOARD_DESC_FLAG_DBG. (V7COR-3896)
09sep15,yya  added warm reboot support. (US63670)
27may14,sye  Fixed build warning for gnu. (V7PRO-904)
13may14,mpc  added BoardInfo show function. (US38743)
01mar14,cfm  created for US29317.
*/

/*
DESCRIPTION
This library provides board-specific routines for zynq series
processor.

INCLUDE FILES:

SEE ALSO:
\tb VxWorks Programmer's Guide: Configuration
*/

/* includes */

#include <vxWorks.h>
#include <boardLib.h>
#include <prjParams.h>
#include <xlnx_zynq7k.h>

#ifdef INCLUDE_SYS_MEM_MGMT
#include <arch/arm/mmuArmLib.h>
#include <private/memPartLibP.h>
#endif /* INCLUDE_SYS_MEM_MGMT */

#ifdef INCLUDE_SHOW_ROUTINES
#include <stdio.h>
#include <stdlib.h>
#include <vmLibCommon.h>
#include <pmapLib.h>
#include <vxFdtLib.h>

/* defines */

#define PSS_IDCODE            0x530
#define PS_VERSION            0x80

LOCAL void zynq7kBoardInfo (void);
#endif /* INCLUDE_SHOW_ROUTINES */

BOARD_FUNC_TBL zynqFuncTbl =
    {
    /* .earlyInit  = */ zynq7kEarlyInit,
    /* .init       = */ zynq7kInit,
    /* .reset      = */ zynq7kReset,
    /* .model      = */ zynq7kModel,
    /* .usDelay    = */ zynq7kUsDelay,
#ifdef _WRS_CONFIG_SMP
    /* .cpuEn      = */ zynq7kCpuEnable,
    /* .cpuAvail   = */ zynq7kCpuAvail,
    /* .cpuDis     = */ NULL,
#endif /*_WRS_CONFIG_SMP */
#ifdef INCLUDE_SHOW_ROUTINES
    /* .infoShow   = */ zynq7kBoardInfo,
#else
    /* .infoShow   = */ NULL,
#endif /* INCLUDE_SHOW_ROUTINES */
    /* .endMacGet  = */ NULL
};

/* locals */

LOCAL BOARD_DESC zynq7kBoardDesc =
    {
    /* .uVer     = */ BOARD_DESC_VER_3_0,
    /* .pCompat  = */ "xlnx,zynq-7000",

#if defined(INCLUDE_DEBUG_KPRINTF) || defined(INCLUDE_DEBUG_KPUTS)
    /* .uFlag    = */ BOARD_DESC_FLAG (BOARD_DESC_FLAG_DBG, 0),
#else /* !INCLUDE_DEBUG_KPRINTF */
    /* .uFlag    = */ BOARD_DESC_FLAG (0, 0),
#endif /* INCLUDE_DEBUG_KPRINTF */

    /* .probe    = */ zynq7kProbe,
    /* .pFuncTbl = */ &zynqFuncTbl
    };

BOARD_DEF (zynq7kBoardDesc)

#ifdef INCLUDE_SHOW_ROUTINES
/*******************************************************************************
*
* zynq7kboardInfo - print board information
*
* This routine prints board information.
*
* RETURNS: N/A
* ERRNO: N/A
*
*/

LOCAL void zynq7kBoardInfo (void)
    {
    void * virtAddr;
    UINT32 phyaddr;
    int    offset;
    UINT32 *prop;
    UINT32 devId;
    UINT32 rev;

    /* get cpu id from slcr register */

    offset = vxFdtPathOffset("/amba/ps7-slcr");
    if (offset <= 0)
        {
        printf("ERROR: no slcr unit present in this board\n");
        return;
        }
    prop = (UINT32*)vxFdtPropGet (offset, "reg", NULL);
    phyaddr = vxFdt32ToCpu (*prop);

    virtAddr = pmapGlobalMap ((PHYS_ADDR) phyaddr,(size_t) 0x1000,
        MMU_ATTR_SUP_RW | MMU_ATTR_CACHE_OFF | MMU_ATTR_CACHE_GUARDED);

    if (virtAddr == PMAP_FAILED)
        {
        printf ("pmapGlobalMap returned ERROR.\n");
        return;
        }

    devId = ((*(UINT32*)((char*)virtAddr + PSS_IDCODE)) >> 12) & 0x1F;

    /* get ps version from dev cfg register */

    offset = vxFdtPathOffset("/amba/ps7-dev-cfg");
    if (offset <= 0)
        {
        printf("ERROR: no dev-cfg unit present in this board\n");
        return;
        }
    prop = (UINT32*)vxFdtPropGet (offset, "reg", NULL);
    phyaddr = vxFdt32ToCpu (*prop);

    virtAddr = pmapGlobalMap ((PHYS_ADDR) phyaddr,(size_t) 0x1000,
        MMU_ATTR_SUP_RW | MMU_ATTR_CACHE_OFF | MMU_ATTR_CACHE_GUARDED);

    if (virtAddr == PMAP_FAILED)
        {
        printf ("pmapGlobalMap returned ERROR.\n");
        return;
        }

    rev = ((*(UINT32*)((char*)virtAddr + PS_VERSION)) >> 28) & 0xF;

    printf ("Xilinx ZC70x Evaluation Kit(unknown revision), ");

    printf ("CPU:");

    switch (devId)
        {
        case 0x02:
            printf ("7z010 ");
            break;
        case 0x07:
            printf ("7z020 ");
            break;
        case 0x0c:
            printf ("7z030 ");
            break;
        case 0x11:
            printf ("7z045 ");
            break;
        default:
            printf ("unknown SOC ");
            break;
        }

    printf ("Rev ");

    switch (rev)
        {
        case 0:
            printf("1.0, ");
            break;
        case 1:
            printf("2.0, ");
            break;
        case 2:
            printf("3.0, ");
            break;
        case 3:
            printf("3.1, ");
        default:
            printf("0x%x, ", rev);
            break;
        }

    /* show core version */

    cpuArmVerShow();

    return;
    }
#endif /* INCLUDE_SHOW_ROUTINES */

#ifdef INCLUDE_SYS_MEM_MGMT
 
/*******************************************************************************
 *
 * zynq7kNetMalloc - allocate memory for network
 *
 * This routine allocates normal un-cached memory for network.
 *
 * RETURNS: Pointer to the memory on success, otherwise NULL.
 *
 * \NOMANUAL
 */
 
void * zynq7kNetMalloc
    (
    size_t size
    )
    {
    void        * pBuf;
    size_t        pageSize;
 
    pageSize = VM_PAGE_SIZE_GET ();
    size = ROUND_UP (size, pageSize);
    if ((pBuf = (void *) KMEM_ALIGNED_ALLOC (size, pageSize)) == NULL)
        return NULL;
 
    if (VM_STATE_SET (NULL, pBuf, size, MMU_ATTR_CACHE_MSK | 
                      MMU_ATTR_VALID_MSK | MMU_ATTR_SPL_MSK,
                      MMU_ATTR_CACHE_OFF | MMU_ATTR_VALID | MMU_ATTR_SPL_0
                      ) != OK)
        {
        free (pBuf);
        return NULL;
        }
 
    return pBuf;
    }
 
/*******************************************************************************
 *
 * zynq7kNetFree - free memory
 *
 * This routine sets the CACHE and SPL attributes of the memory to default, 
 * then frees it.
 *
 * RETURNS: N/A
 *
 * \NOMANUAL
 */

void zynq7kNetFree
    (
    void *      pBuf
    )
    {
    VM_INFO vmInfo = {0};
 
    if (vmInfoGet (&vmInfo) == ERROR)
        {
        vmInfo.ramDefaultAttr = MMU_ATTR_CACHE_DEFAULT;
        }
 
    (void)VM_STATE_SET (NULL, pBuf,
                        ROUND_DOWN (MEM_BLOCK_SIZE (pBuf), VM_PAGE_SIZE_GET ()),
                        MMU_ATTR_CACHE_MSK | MMU_ATTR_SPL_MSK, 
                        vmInfo.ramDefaultAttr);
 
    free (pBuf);                /* free buffer after modified */
}

#endif /* INCLUDE_SYS_MEM_MGMT */

